import streamlit as st
import pandas as pd
import os
from pathlib import Path
import sys
import subprocess
import json
import traceback
import html
import time

# 添加项目路径
project_root = Path(__file__).parent.parent
sys.path.append(str(project_root))
sys.path.append(str(project_root / "src"))

st.set_page_config(
    page_title="数据管理 - RAG-main",
    page_icon="📊",
    layout="wide"
)

# 自定义CSS
st.markdown("""
<style>
    .success-box {
        background-color: #d4edda;
        border: 1px solid #c3e6cb;
        border-radius: 5px;
        padding: 10px;
        margin: 10px 0;
    }
    .error-box {
        background-color: #f8d7da;
        border: 1px solid #f5c6cb;
        border-radius: 5px;
        padding: 10px;
        margin: 10px 0;
    }
    .info-box {
        background-color: #d1ecf1;
        border: 1px solid #bee5eb;
        border-radius: 5px;
        padding: 10px;
        margin: 10px 0;
    }
</style>
""", unsafe_allow_html=True)

st.title("📊 数据管理")
st.markdown("管理 PDF 文档、解析状态和数据库")

def safe_read_csv(file_path):
    """安全读取CSV文件，尝试多种编码"""
    encodings = ['utf-8', 'gbk', 'gb2312', 'latin-1', 'cp1252']
    
    for encoding in encodings:
        try:
            return pd.read_csv(file_path, encoding=encoding)
        except UnicodeDecodeError:
            continue
        except Exception as e:
            st.error(f"读取文件时发生错误: {e}")
            return None
    
    st.error("无法读取文件，尝试了多种编码方式都失败")
    return None

def check_project_structure():
    """检查项目结构完整性"""
    required_paths = {
        "data/stock_data": "数据目录",
        "data/stock_data/pdf_reports": "PDF文件目录",
        "src": "源代码目录"
    }
    
    missing_paths = []
    for path, desc in required_paths.items():
        if not Path(path).exists():
            missing_paths.append(f"{desc} ({path})")
    
    return missing_paths

def run_command_safely(cmd, cwd=None):
    print(f"Running command: {' '.join(cmd)}")
    """安全执行命令"""
    try:
        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
            cwd=cwd,
            timeout=1800  # 30分钟超时
        )
        return result
    except subprocess.TimeoutExpired:
        st.error("命令执行超时（30分钟）")
        return None
    except Exception as e:
        st.error(f"命令执行失败: {e}")
        return None

def stream_command_logs(cmd, cwd=None, env=None, height: int = 280):
    """
    启动子进程，实时将其标准输出/错误输出写入到界面（类似命令行滚动日志）。
    - height: 日志显示区域固定高度（像素），带垂直滚动条。
    - env: 环境变量字典，如果为None则使用当前环境
    返回子进程的退出码（0 表示成功）。
    """
    try:
        placeholder = st.empty()
        log_lines = []
        process = subprocess.Popen(
            cmd,
            cwd=cwd,
            env=env,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            bufsize=1,
            universal_newlines=True,
            text=True,
        )
        # 持续读取并刷新到界面（使用 HTML <pre> 固定高度+滚动）
        while True:
            line = process.stdout.readline()
            if line == '' and process.poll() is not None:
                break
            if line:
                log_lines.append(line.rstrip('\n'))
                safe_html = html.escape("\n".join(log_lines))
                placeholder.markdown(
                    f"""
<style>
.log-box {{
  max-height: {height}px;
  height: {height}px;
  overflow-y: auto;
  background: #0b1021;
  color: #d6e3ff;
  border: 1px solid #2b3a67;
  border-radius: 6px;
  padding: 10px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
  font-size: 12px;
  line-height: 1.5;
  white-space: pre-wrap;
}}
</style>
<div class="log-box">{safe_html}</div>
                    """,
                    unsafe_allow_html=True,
                )
        process.stdout.close()
        return process.wait()
    except Exception as e:
        st.error(f"启动或读取子进程输出失败: {e}")
        return -1

# ---- 新增: 目录签名计算（用于自动刷新 PDF 列表）----
def compute_dir_signature(target_dir: Path) -> str:
    """
    计算目录签名，用于快速判断目录内容是否发生变化。
    将文件名、大小、修改时间组合后做一个可比对的字符串。
    仅统计 *.pdf 与 *.PDF。
    """
    if not target_dir.exists():
        return "<missing>"
    parts = []
    for p in sorted(list(target_dir.glob("*.pdf")) + list(target_dir.glob("*.PDF"))):
        try:
            stat = p.stat()
            parts.append(f"{p.name}|{stat.st_size}|{int(stat.st_mtime)}")
        except Exception:
            # 若某个文件读取失败，不影响整体签名计算
            parts.append(f"{p.name}|error")
    return "::".join(parts) or "<empty>"

# 检查项目结构
missing_paths = check_project_structure()
if missing_paths:
    st.error("⚠️ 项目结构不完整")
    for path in missing_paths:
        st.write(f"❌ 缺少: {path}")
    st.info("请确保在正确的项目目录中运行此应用")

# 初始化持久化状态（操作结果提示）
if 'parse_status' not in st.session_state:
    st.session_state.parse_status = None
if 'report_status' not in st.session_state:
    st.session_state.report_status = None
if 'full_status' not in st.session_state:
    st.session_state.full_status = None

# 初始化目录签名状态
if "pdf_reports_dirty" not in st.session_state:
    st.session_state["pdf_reports_dirty"] = False
if "pdf_reports_signature" not in st.session_state:
    pdf_dir = Path("data/stock_data/pdf_reports")
    st.session_state["pdf_reports_signature"] = compute_dir_signature(pdf_dir)

# 侧边栏
with st.sidebar:
    st.header("操作选项")
    
    # PDF 解析器选择
    parser_choice = st.selectbox(
        "选择解析器",
        ["mineru", "docling"],
        help="选择用于解析 PDF 的工具"
    )
    
    # 并行处理选项（仅 Docling）
    if parser_choice == "docling":
        use_parallel = st.checkbox("启用并行处理", value=True)
        if use_parallel:
            max_workers = st.slider("最大工作进程", 1, 8, 4)
            chunk_size = st.slider("批处理大小", 1, 10, 2)
    
    # MinerU 模式选择（仅 MinerU）
    if parser_choice == "mineru":
        mineru_mode = st.selectbox(
            "MinerU 模式",
            ["local", "cloud"],
            help="选择 MinerU 解析模式：local（本地模式，需要安装 magic-pdf）或 cloud（云端 API 模式）"
        )
    
    # 配置选择
    config_choice = st.selectbox(
        "处理配置",
        ["max", "base", "pdr"],
        help="选择处理配置"
    )
    
    # 显示当前状态
    st.markdown("---")
    st.subheader("📊 快速状态")
    
    # 检查各种文件状态
    data_path = Path("data/stock_data")
    if data_path.exists():
        pdf_count = len(list((data_path / "pdf_reports").glob("*.pdf"))) if (data_path / "pdf_reports").exists() else 0
        md_count = len(list((data_path / "debug_data" / "03_reports_markdown").glob("*.md"))) if (data_path / "debug_data" / "03_reports_markdown").exists() else 0
        json_count = len(list((data_path / "databases" / "chunked_reports").glob("*.json"))) if (data_path / "databases" / "chunked_reports").exists() else 0
        faiss_count = len(list((data_path / "databases" / "vector_dbs").glob("*.faiss"))) if (data_path / "databases" / "vector_dbs").exists() else 0
        
        st.metric("PDF 文件", pdf_count)
        st.metric("解析结果", md_count)
        st.metric("分块数据", json_count)
        st.metric("向量索引", faiss_count)

# 主内容区域
tab1, tab2, tab3, tab4 = st.tabs(["📁 文件管理", "🔄 PDF 解析", "🗄️ 数据库状态", "⚙️ 系统配置"])

with tab1:
    st.header("PDF 文件管理")
    
    # 显示 PDF 文件列表
    pdf_dir = Path("data/stock_data/pdf_reports")
    
    # 文件管理页：只在启动时或手动操作后刷新一次
    current_signature = compute_dir_signature(pdf_dir)
    stored_signature = st.session_state.pdf_reports_signature
    
    # 只在签名确实发生变化时才刷新
    if current_signature != stored_signature:
        st.session_state.pdf_reports_signature = current_signature
        st.rerun()
    
    if pdf_dir.exists():
        # 修复重复文件问题：使用集合去重
        pdf_files_set = set()
        for pattern in ["*.pdf", "*.PDF"]:
            for pdf_file in pdf_dir.glob(pattern):
                pdf_files_set.add(pdf_file)
        pdf_files = sorted(pdf_files_set, key=lambda x: x.name)
        
        if pdf_files:
            st.success(f"✅ 找到 {len(pdf_files)} 个 PDF 文件")
            
            # 创建文件信息表格
            file_data = []
            for pdf_file in pdf_files:
                try:
                    stat = pdf_file.stat()
                    file_data.append({
                        "文件名": pdf_file.name,
                        "大小 (MB)": f"{stat.st_size / (1024*1024):.2f}",
                        "修改时间": pd.to_datetime(stat.st_mtime, unit='s').strftime('%Y-%m-%d %H:%M:%S')
                    })
                except Exception as e:
                    st.warning(f"无法读取文件 {pdf_file.name} 的信息: {e}")
            
            if file_data:
                df = pd.DataFrame(file_data)
                st.dataframe(df, use_container_width=True)
            
            # 文件上传
            st.subheader("📤 上传新的 PDF 文件")
            uploaded_files = st.file_uploader(
                "选择 PDF 文件",
                type=['pdf','PDF'],
                accept_multiple_files=True,
                help="支持同时上传多个 PDF 文件"
            )
            
            if uploaded_files:
                success_count = 0
                for uploaded_file in uploaded_files:
                    try:
                        # 保存文件
                        save_path = pdf_dir / uploaded_file.name
                        with open(save_path, "wb") as f:
                            f.write(uploaded_file.getbuffer())
                        success_count += 1
                    except Exception as e:
                        st.error(f"保存文件 {uploaded_file.name} 失败: {e}")
                
                if success_count > 0:
                    st.success(f"✅ 成功上传 {success_count} 个文件")
                    # 写入跨页刷新标记，通知“PDF 解析”页自动更新列表
                    st.session_state["pdf_reports_dirty"] = True
                    # 文件管理页只刷新一次
                    st.session_state.pdf_reports_signature = compute_dir_signature(pdf_dir)
                    st.rerun()
        else:
            st.warning("📂 未找到 PDF 文件")
            st.info("请上传 PDF 文件到 pdf_reports 目录")
    else:
        st.error("❌ PDF 目录不存在")
        if st.button("创建 PDF 目录"):
            try:
                pdf_dir.mkdir(parents=True, exist_ok=True)
                st.success("✅ PDF 目录创建成功")
                st.rerun()
            except Exception as e:
                st.error(f"创建目录失败: {e}")

with tab2:
    st.header("PDF 解析处理")
    
    pdf_dir = Path("data/stock_data/pdf_reports")
    if "pdf_reports_dirty" not in st.session_state:
        st.session_state["pdf_reports_dirty"] = False
    if "pdf_reports_signature" not in st.session_state:
        st.session_state["pdf_reports_signature"] = None

    current_signature = compute_dir_signature(pdf_dir)
    stored_signature = st.session_state.pdf_reports_signature
    dir_changed = stored_signature != current_signature
    dirty_flag = st.session_state.pdf_reports_dirty

    if dir_changed or dirty_flag:
        st.session_state.pdf_reports_signature = current_signature
        st.session_state.pdf_reports_dirty = False
        if stored_signature is not None and dir_changed:
            st.info("📂 检测到 PDF 目录有更新，列表已自动刷新")
    
    col1, col2 = st.columns(2)
    
    with col1:
        st.subheader("🔄 解析 PDF 文档")
        
        # 检查是否有PDF文件（兼容 .pdf 和 .PDF）
        pdf_count = (len(list(pdf_dir.glob("*.pdf"))) + len(list(pdf_dir.glob("*.PDF")))) if pdf_dir.exists() else 0
        
        if pdf_count == 0:
            st.warning("⚠️ 没有找到 PDF 文件，请先上传文件")
        else:
            # 展示所有 PDF 文件列表 + 是否已解析（03_reports_markdown 下有对应 .md 即视为已解析）
            markdown_dir = Path("data/stock_data/debug_data/03_reports_markdown")
            parsed_set = {p.stem for p in markdown_dir.glob("*.md")} if markdown_dir.exists() else set()
            all_pdfs = sorted({p.name for p in list(pdf_dir.glob("*.pdf")) + list(pdf_dir.glob("*.PDF"))})
            default_selected = [i for i, name in enumerate(all_pdfs)]  # 默认全选，允许用户取消
            labels = [f"{name} {'(已解析)' if Path(name).stem in parsed_set else ''}" for name in all_pdfs]
            selected_indexes = st.multiselect(
                "请选择要解析为 Markdown 的 PDF（可多选，已解析的也可重复解析）",
                options=list(range(len(all_pdfs))),
                default=default_selected,
                format_func=lambda i: labels[i],
                help="未勾选的将不会解析；已解析标记仅供参考，允许重复解析"
            )
            col_a, _ = st.columns([1,1])
            with col_a:
                st.caption(f"共发现 {len(all_pdfs)} 个 PDF 文件")

        if st.button("🔄 开始解析 PDF", type="primary", disabled=(pdf_count == 0)):
            st.session_state.parse_status = None  # 新一轮解析前重置该项状态
            st.info("📟 实时解析日志（与命令行一致）：")
            
            # 确保使用正确的环境配置：复制当前环境并设置正确的MINERU_MODE
            env = os.environ.copy()
            
            # 对于mineru解析器，确保使用正确的模式
            if parser_choice == "mineru":
                # 优先使用用户选择的模式
                if 'mineru_mode' in locals():
                    env['MINERU_MODE'] = mineru_mode
                else:
                    # 如果没有用户选择，默认使用cloud模式（避免本地模式问题）
                    env['MINERU_MODE'] = 'cloud'
                
                # 确保API密钥可用（使用默认密钥）
                if 'MINERU_API_KEY' not in env or not env['MINERU_API_KEY']:
                    env['MINERU_API_KEY'] = 'eyJ0eXBlIjoiSldUIiwiYWxnIjoiSFM1MTIifQ.eyJqdGkiOiIxODkwNDM1MCIsInJvbCI6IlJPTEVfUkVHSVNURVIiLCJpc3MiOiJPcGVuWExhYiIsImlhdCI6MTc0ODY5NjQ3MSwiY2xpZW50SWQiOiJsa3pkeDU3bnZ5MjJqa3BxOXgydyIsInBob25lIjoiMTU4MDE0MzgzODYiLCJvcGVuSWQiOm51bGwsInV1aWQiOiIwYmNiYmU5NC0yMTliLTRiMjMtYjFiZi05ZWE5ZDZjZjQ0OTMiLCJlbWFpbCI6IiIsImV4cCI6MTc0OTkwNjA3MX0.CflSvU6KF09ZxYLrW9uzXAjK24VYaDh3WMEaDDGeTbbU17n4n3pSbc4zMaWpchEAwPiwuVGahb_ak7XjgK0dpw'
            
            cmd = ["python", "../../main.py", "parse-pdfs", "--parser", parser_choice]
            if parser_choice == "docling" and 'use_parallel' in locals() and use_parallel:
                cmd.extend(["--parallel", "--max-workers", str(max_workers), "--chunk-size", str(chunk_size)])
            # 若选择 MinerU 且用户勾选了部分文件，则通过 --files 传递具体文件名
            if parser_choice == "mineru" and 'selected_indexes' in locals() and selected_indexes:
                selected_files = [all_pdfs[i] for i in selected_indexes]
                for f in selected_files:
                    cmd.extend(["--files", f])
            
            # 添加详细的调试信息
            st.info(f"解析命令: {' '.join(cmd)}")
            st.info(f"解析器: {parser_choice}")
            if parser_choice == "mineru":
                st.info(f"MinerU 模式: {env.get('MINERU_MODE', '未设置')}")
                st.info(f"API密钥状态: {'已配置' if env.get('MINERU_API_KEY') else '使用默认'}")
            if parser_choice == "mineru" and 'selected_files' in locals():
                st.info(f"选中的文件: {selected_files}")
            
            # 添加环境检查
            st.info("🔍 环境检查:")
            st.info(f"工作目录: {Path('data/stock_data').absolute()}")
            st.info(f"PDF文件路径: {Path('data/stock_data/pdf_reports').absolute()}")
            
            returncode = stream_command_logs(cmd, cwd="data/stock_data", env=env)
            if returncode == 0:
                st.session_state.parse_status = ("success", "✅ PDF 解析完成！")
                st.session_state.pdf_reports_dirty = True
                time.sleep(0.5)
                st.rerun()
            elif returncode == -1:
                st.session_state.parse_status = ("error", "❌ 解析启动失败（请查看上方错误提示）")
            else:
                st.session_state.parse_status = ("error", f"❌ 解析失败（退出码 {returncode}）")
            
        # 持久化显示上次解析操作结果（始终展示在日志下方，直到下一次点击解析）
        if st.session_state.parse_status:
            status, message = st.session_state.parse_status
            if status == "success":
                st.success(message)
            else:
                st.error(message)
            

        st.markdown("---")
        st.subheader("📊 处理解析结果")
        
        # 检查是否有解析结果
        markdown_dir = Path("data/stock_data/debug_data/03_reports_markdown")
        md_count = len(list(markdown_dir.glob("*.md"))) if markdown_dir.exists() else 0
        
        if md_count == 0:
            st.warning("⚠️ 没有找到解析结果，请先解析 PDF")
        else:
            st.info(f"📄 找到 {md_count} 个解析结果")
        
        if st.button("📊 处理报告数据", type="secondary", disabled=(md_count == 0)):
            st.session_state.report_status = None  # 新一轮处理前重置该项状态
            st.info("📟 实时处理日志：")
            config_suffix = "no_ser_tab" if parser_choice == "mineru" else "ser_tab"
            cmd = [sys.executable, "../../main.py", "process-reports", "--config", config_suffix, "--parser", parser_choice]
            returncode = stream_command_logs(cmd, cwd="data/stock_data")
            if returncode == 0:
                st.session_state.report_status = ("success", "✅ 报告处理完成！")
                time.sleep(0.5)
                st.rerun()
            elif returncode == -1:
                st.session_state.report_status = ("error", "❌ 处理启动失败（请查看上方错误提示）")
            else:
                st.session_state.report_status = ("error", f"❌ 处理失败（退出码 {returncode}）")
        
        # 持久化结果提示（显示在日志下方，直到下一次点击处理）
        if st.session_state.report_status:
            status, message = st.session_state.report_status
            if status == "success":
                st.success(message)
            else:
                st.error(message)
    with col2:
      
        
        # 一键完整处理
        #st.markdown("---")
        st.subheader("🚀 一键完整处理")
        st.caption("包含解析PDF + 处理数据 + 创建向量库")
        
        if st.button("🚀 一键完整处理", type="primary", disabled=(pdf_count == 0)):
            st.session_state.full_status = None  # 新一轮完整处理前重置该项状态
            st.info("📟 实时处理日志：")
            cmd = [sys.executable, "../../main.py", "process-all-pdfs", "--parser", parser_choice]
            if parser_choice == "docling" and 'use_parallel' in locals() and use_parallel:
                cmd.extend(["--parallel"])
            returncode = stream_command_logs(cmd, cwd="data/stock_data")
            if returncode == 0:
                st.session_state.full_status = ("success", "✅ 完整处理完成！")
                time.sleep(0.5)
                st.rerun()
            elif returncode == -1:
                st.session_state.full_status = ("error", "❌ 启动失败（请查看上方错误提示）")
            else:
                st.session_state.full_status = ("error", f"❌ 处理失败（退出码 {returncode}）")
        
        # 持久化结果提示（显示在日志下方，直到下一次点击完整处理）
        if st.session_state.full_status:
            status, message = st.session_state.full_status
            if status == "success":
                st.success(message)
            else:
                st.error(message)

with tab3:
    st.header("🗄️ 数据库状态")
    
    # 检查各种数据库文件
    data_path = Path("data/stock_data")
    
    col1, col2, col3 = st.columns(3)
    
    with col1:
        st.subheader("📄 解析结果")
        markdown_dir = data_path / "debug_data" / "03_reports_markdown"
        if markdown_dir.exists():
            md_files = list(markdown_dir.glob("*.md"))
            st.metric("Markdown 文件", len(md_files))
            
            if md_files:
                st.write("📝 最近解析的文件:")
                for md_file in md_files[-3:]:
                    st.write(f"• {md_file.name}")
                
                # 显示文件大小统计
                total_size = sum(f.stat().st_size for f in md_files) / (1024*1024)
                st.write(f"📊 总大小: {total_size:.2f} MB")
        else:
            st.warning("📂 未找到解析结果目录")
    
    with col2:
        st.subheader("🗂️ 分块数据")
        chunked_dir = data_path / "databases" / "chunked_reports"
        if chunked_dir.exists():
            json_files = list(chunked_dir.glob("*.json"))
            st.metric("分块文件", len(json_files))
            
            if json_files:
                st.write("📋 分块数据文件:")
                for json_file in json_files[-3:]:
                    st.write(f"• {json_file.name}")
                
                # 显示分块统计
                try:
                    total_chunks = 0
                    for json_file in json_files:
                        with open(json_file, 'r', encoding='utf-8') as f:
                            data = json.load(f)
                            chunks = data.get('content', {}).get('chunks', [])
                            total_chunks += len(chunks)
                    st.write(f"📊 总分块数: {total_chunks}")
                except Exception as e:
                    st.write(f"⚠️ 统计分块数失败: {e}")
        else:
            st.warning("📂 未找到分块数据目录")
    
    with col3:
        st.subheader("🔍 向量数据库")
        vector_dir = data_path / "databases" / "vector_dbs"
        if vector_dir.exists():
            faiss_files = list(vector_dir.glob("*.faiss"))
            st.metric("FAISS 索引", len(faiss_files))
            
            if faiss_files:
                st.write("🔍 向量索引文件:")
                for faiss_file in faiss_files[-3:]:
                    st.write(f"• {faiss_file.name}")
                
                # 显示索引文件大小
                total_size = sum(f.stat().st_size for f in faiss_files) / (1024*1024)
                st.write(f"📊 总大小: {total_size:.2f} MB")
        else:
            st.warning("📂 未找到向量数据库目录")
    
    # 详细状态信息
    st.subheader("📋 详细状态")
    
    # 检查 subset.csv
    subset_file = data_path / "subset.csv"
    if subset_file.exists():
        try:
            df = safe_read_csv(subset_file)
            if df is not None:
                st.success(f"✅ 找到 subset.csv，包含 {len(df)} 条记录")
                
                # 显示列信息
                st.write("📊 数据列:")
                for col in df.columns:
                    st.write(f"• {col}: {df[col].dtype}")
                
                # 显示数据预览
                st.write("📄 数据预览:")
                st.dataframe(df.head(), use_container_width=True)
                
                # 公司统计
                if 'company_name' in df.columns:
                    companies = df['company_name'].unique()
                    st.write(f"🏢 包含公司: {len(companies)} 家")
                    for company in companies:
                        count = len(df[df['company_name'] == company])
                        st.write(f"  • {company}: {count} 个文件")
        except Exception as e:
            st.error(f"❌ 读取 subset.csv 文件失败: {e}")
            st.write("🔧 尝试的解决方案:")
            st.write("1. 检查文件编码是否正确")
            st.write("2. 检查文件是否被其他程序占用")
            st.write("3. 检查文件权限")
    else:
        st.error("❌ 未找到 subset.csv 文件")
        st.info("💡 subset.csv 文件包含文件和公司的映射关系，是系统正常运行的必要文件")

with tab4:
    st.header("⚙️ 系统配置")
    if parser_choice == "mineru":
        col1, col2 = st.columns(2)
    
        with col1:
            st.subheader("🔧 MinerU 配置")
        
            # 显示当前模式
            try:
                from src.pdf_mineru import get_current_mode, set_mode
                current_mode = get_current_mode()
                st.info(f"📍 当前模式: {current_mode}")
                
                # 模式切换
                new_mode = st.selectbox(
                    "切换模式", 
                    ["local", "cloud"], 
                    index=0 if current_mode == "local" else 1,
                    help="local: 本地处理，cloud: 云端API"
                )
                
                if st.button("🔄 应用模式"):
                    try:
                        set_mode(new_mode)
                        st.success(f"✅ 已切换到 {new_mode} 模式")
                        st.rerun()
                    except Exception as e:
                        st.error(f"❌ 切换模式失败: {e}")
                        
            except Exception as e:
                st.error(f"❌ MinerU 配置错误: {e}")
                st.write("🔧 可能的解决方案:")
                st.write("1. 检查 src/pdf_mineru.py 文件是否存在")
                st.write("2. 检查 MinerU 是否正确安装")
    
        with col2:
            st.subheader("💻 环境信息")
            
            # 显示 Python 环境信息
            st.write(f"**🐍 Python 版本**: {sys.version.split()[0]}")
            st.write(f"**📁 工作目录**: {os.getcwd()}")
            st.write(f"**🏠 项目根目录**: {project_root}")
            
            # 检查关键模块
            modules_to_check = [
                ("streamlit", "Web界面框架"),
                ("pandas", "数据处理"),
                ("numpy", "数值计算"), 
                ("faiss", "向量检索"),
                ("sentence_transformers", "文本嵌入")
            ]
            
            st.write("**📦 模块状态**:")
            for module, desc in modules_to_check:
                try:
                    __import__(module)
                    st.write(f"✅ {module} - {desc}")
                except ImportError:
                    st.write(f"❌ {module} - {desc} (未安装)")
    else:
        #当前不是MinerU时，环境信息占满整个宽度
        st.subheader("💻 环境信息")
            
        # 显示 Python 环境信息
        st.write(f"**🐍 Python 版本**: {sys.version.split()}")
        st.write(f"**📁 工作目录**: {os.getcwd()}")
        st.write(f"**🏠 项目根目录**: {project_root}")
        
        # 检查关键模块
        modules_to_check = [
            ("streamlit", "Web界面框架"),
            ("pandas", "数据处理"),
            ("numpy", "数值计算"), 
            ("faiss", "向量检索"),
            ("sentence_transformers", "文本嵌入")
        ]
        
        st.write("**📦 模块状态**:")
        for module, desc in modules_to_check:
            try:
                __import__(module)
                st.write(f"✅ {module} - {desc}")
            except ImportError:
                st.write(f"❌ {module} - {desc} (未安装)")
    
    # 系统诊断
    st.subheader("🔍 系统诊断")
    
    if st.button("🔍 运行系统诊断"):
        with st.spinner("正在诊断系统状态..."):
            diagnosis = []
            
            # 检查目录结构
            required_dirs = [
                "data/stock_data",
                "data/stock_data/pdf_reports",
                "src",
                "databases"
            ]
            
            for dir_path in required_dirs:
                if Path(dir_path).exists():
                    diagnosis.append(f"✅ {dir_path} - 存在")
                else:
                    diagnosis.append(f"❌ {dir_path} - 不存在")
            
            # 检查关键文件
            key_files = [
                "main.py",
                "src/pipeline.py",
                "src/pdf_mineru.py"
            ]
            
            for file_path in key_files:
                if Path(file_path).exists():
                    diagnosis.append(f"✅ {file_path} - 存在")
                else:
                    diagnosis.append(f"❌ {file_path} - 不存在")
            
            # 显示诊断结果
            st.write("**诊断结果:**")
            for item in diagnosis:
                st.write(item)
            
            # 给出建议
            failed_items = [item for item in diagnosis if item.startswith("❌")]
            if failed_items:
                st.warning("⚠️ 发现问题，建议:")
                st.write("1. 确保在正确的项目根目录运行")
                st.write("2. 检查项目文件是否完整")
                st.write("3. 重新下载或克隆项目")
            else:
                st.success("🎉 系统状态良好！")